|
ARD2
RC2
Airbag Reference Demonstrator using MPC5604P
|
00001 00017 #include "derivative.h" 00018 #include "utils.h" /* For Parity */ 00019 #include "MMA68xx.h" 00020 #include "DSPI.h" 00021 #include "MailScheduler.h" 00022 #include <limits.h> /* To set limits */ 00023 #include <stdlib.h> 00024 /* 00025 ****************************************************************************** 00026 * constants 00027 ****************************************************************************** 00028 */ 00029 const uint16_t cau16MMA6800Reset[] = 00030 { 00031 /* Sequence below is needed to perform a soft-reset */ 00032 (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | CLEAR), 00033 (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | 0xC0u), 00034 (MMA6800_DEVCTL | (MMA6800_WRITE_REGISTER << CHAR_BIT) | 0x40u), 00035 /* Dummy read after reset */ 00036 (MMA6800_DEVCFG | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), 00037 (MMA6800_DEVCFG | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) }; 00038 00039 const uint16_t cau16MMA6800ReadAllRegisters[] = 00040 { 00041 (MMA6800_SN0 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN1 00042 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN2 00043 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN3 00044 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_X 00045 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_Y 00046 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_PN 00047 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCTL 00048 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG 00049 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_X 00050 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_Y 00051 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGX 00052 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGY 00053 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XP 00054 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YP 00055 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XN 00056 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YN 00057 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVSTAT 00058 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_COUNT 00059 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_X 00060 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_Y 00061 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) }; 00062 00063 const uint16_t cau16MMA6500ReadAllRegisters[] = 00064 { 00065 (MMA6800_SN0 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN1 00066 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN2 00067 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_SN3 00068 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_STDEFL_X 00069 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_STDEFL_Y 00070 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_X 00071 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_FCTCFG_Y 00072 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_PN 00073 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCTL 00074 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG 00075 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_X 00076 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVCFG_Y 00077 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGX 00078 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMCFGY 00079 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XP 00080 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YP 00081 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_XN 00082 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_ARMT_YN 00083 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_DEVSTAT 00084 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_COUNT 00085 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_X 00086 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR), (MMA6800_OFF_CORR_Y 00087 | (MMA6800_READ_REGISTER << CHAR_BIT) | CLEAR) }; 00088 00089 /* Constant table below groups all possible acceleration modes for each */ 00090 /* sensor. */ 00091 const uint16_t cau16MMA6800PerformAccelReading[] = 00092 { 00093 /* Config 0 */ 00094 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\ 00095 00096 | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE), 00097 00098 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\ 00099 00100 | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE), 00101 /* Config 1 */ 00102 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\ 00103 00104 | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE), 00105 00106 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\ 00107 00108 | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE), 00109 /* Config 2 */ 00110 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\ 00111 00112 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00113 00114 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\ 00115 00116 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00117 /* Config 3 */ 00118 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED\ 00119 00120 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00121 00122 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED\ 00123 00124 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00125 /* Config 4 */ 00126 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00127 | MMA6800_ARM_DISABLE), 00128 00129 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00130 | MMA6800_ARM_DISABLE), 00131 /* Config 5 */ 00132 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00133 | MMA6800_ARM_ENABLE), 00134 00135 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00136 | MMA6800_ARM_ENABLE), 00137 /* Config 6 */ 00138 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA 00139 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00140 00141 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA 00142 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00143 /* Config 7 */ 00144 (MMA6800_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA 00145 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00146 00147 (MMA6800_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA 00148 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), }; 00149 00150 const uint16_t cau16MMA6500PerformAccelReading[] = 00151 { 00152 /* Config 0 */ 00153 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED 00154 | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE), 00155 00156 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED 00157 | MMA6800_SIGNED_DATA | MMA6800_ARM_DISABLE), 00158 00159 /* Config 1 */ 00160 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED 00161 | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE), 00162 00163 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED 00164 | MMA6800_SIGNED_DATA | MMA6800_ARM_ENABLE), 00165 00166 /* Config 2 */ 00167 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED 00168 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00169 00170 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED 00171 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00172 00173 /* Config 3 */ 00174 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_OFFSET_CANCELLED 00175 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00176 00177 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_OFFSET_CANCELLED 00178 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00179 00180 /* Config 4 */ 00181 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00182 | MMA6800_ARM_DISABLE), 00183 00184 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00185 | MMA6800_ARM_DISABLE), 00186 00187 /* Config 5 */ 00188 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00189 | MMA6800_ARM_ENABLE), 00190 00191 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA | MMA6800_SIGNED_DATA 00192 | MMA6800_ARM_ENABLE), 00193 00194 /* Config 6 */ 00195 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA 00196 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00197 00198 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA 00199 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_DISABLE), 00200 00201 /* Config 7 */ 00202 (MMA6500_READ_ACCEL | MMA6800_X_AXIS | MMA6800_RAW_DATA 00203 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), 00204 00205 (MMA6500_READ_ACCEL | MMA6800_Y_AXIS | MMA6800_RAW_DATA 00206 | MMA6800_UNSIGNED_DATA | MMA6800_ARM_ENABLE), }; 00207 00208 /* The element below is a constant array of pointers to functions */ 00209 /* with two elements, namely the address of the scheduled and the */ 00210 /* immediate transfers. This solution allows the user to send either */ 00211 /* command just by choosing the index in the array. */ 00212 uint8_t (* const u8pfnMMA6800BatchOp[])(const uint8_t cu8DSPIInstance, 00213 const uint8_t cu8ChipSelect, 00214 const uint16_t* pu16DataToSend, 00215 uint16_t* pu16UnfilteredDataReceived, 00216 uint8_t u8Size) = 00217 00218 { 00219 &u8fnMMA6800ScheduledBatchOp, &u8fnMMA6800BatchOp }; 00220 /* 00221 ****************************************************************************** 00222 * Globals 00223 ****************************************************************************** 00224 */ 00225 /* Global variable array that allows "trash" responses to be scheduled safely*/ 00226 uint8_t gau8MMA6800GlobalResult[MMA6800_GLOBAL_BUFFER_SIZE]; 00227 /* 00228 ****************************************************************************** 00229 * u8fnMMA6800ReadRegister 00230 ****************************************************************************** 00231 */ 00232 uint8_t u8fnMMA6800ReadRegister(const uint8_t cu8DSPIInstance, 00233 const uint8_t cu8ChipSelect, 00234 const uint8_t cu8TransferMode, 00235 uint16_t u16Register, uint16_t* pu16DataRead) 00236 { 00237 uint16_t u16ReadCmd; 00238 00239 /* Create data to be sent in the correct format */ 00240 u16ReadCmd = (uint16_t)((MMA6800_READ_REGISTER << 8u) | u16Register); 00241 00242 /* Call the correct fn according to cu8TransferMode */ 00243 return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance, 00244 cu8ChipSelect, 00245 (uint16_t*)&u16ReadCmd, 00246 pu16DataRead, 1u)); 00247 } 00248 /* 00249 ****************************************************************************** 00250 * u8fnMMA6800WriteRegister 00251 ****************************************************************************** 00252 */ 00253 uint8_t u8fnMMA6800WriteRegister(const uint8_t cu8DSPIInstance, 00254 const uint8_t cu8ChipSelect, 00255 const uint8_t cu8TransferMode, 00256 uint16_t u16Register, uint8_t u8ValueToWrite, 00257 uint16_t* pu16DataRead) 00258 { 00259 uint16_t u16WriteCmd; 00260 00261 u16WriteCmd = (uint16_t)((MMA6800_WRITE_REGISTER << 8u) | u16Register 00262 | u8ValueToWrite); 00263 00264 /* Call the correct fn according to cu8TransferMode */ 00265 return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance, 00266 cu8ChipSelect, 00267 (uint16_t*)&u16WriteCmd, 00268 pu16DataRead, 1u)); 00269 } 00270 /* 00271 ****************************************************************************** 00272 * u8fnMMA6800Reset 00273 ****************************************************************************** 00274 */ 00275 uint8_t u8fnMMA6800Reset(const uint8_t cu8DSPIInstance, 00276 const uint8_t cu8ChipSelect, 00277 const uint8_t cu8TransferMode) 00278 { 00279 00280 /* Call the correct fn according to cu8TransferMode */ 00281 return ((*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance, 00282 cu8ChipSelect, 00283 (uint16_t*)cau16MMA6800Reset, 00284 (uint16_t*)gau8MMA6800GlobalResult, 00285 (uint8_t)N_ELEMENTS(cau16MMA6800Reset))); 00286 } 00287 /* 00288 ****************************************************************************** 00289 * u8fnMMA6800ReadAccel 00290 ****************************************************************************** 00291 */ 00292 uint8_t u8fnMMA6800ReadAccel(const uint8_t cu8DSPIInstance, 00293 const uint8_t cu8ChipSelect, 00294 const uint8_t cu8TransferMode, 00295 const uint8_t cu8Axis, 00296 const uint8_t cu8ConfigMemory, 00297 uint16_t* pu16AccelResults, const uint8_t cu8Accel) 00298 { 00299 /* Declare locals */ 00300 uint8_t u8Index; 00301 uint8_t u8Status; 00302 uint8_t u8Counter; 00303 uint8_t u8Offset; 00304 uint16_t* pu16AccelTable; 00305 00306 /* Init locals */ 00307 u8Status = CLEAR; 00308 u8Index = CLEAR; 00309 u8Offset = CLEAR; 00310 u8Counter = (uint8_t)1u; 00311 pu16AccelTable = (uint16_t*)&cau16MMA6800PerformAccelReading; 00312 00313 /* Figure out where in the table we are */ 00314 if(cu8ConfigMemory >= (N_ELEMENTS(cau16MMA6800PerformAccelReading) / 2u)) 00315 { 00316 /* This is bad - we are out of the table. flag it as an error and exit */ 00317 u8Status = MMA6800_INVALID_MEMORY_LOCATION; 00318 } 00319 else 00320 { 00321 /* Figure out how many readings we need - this will change the offset */ 00322 /* within the table */ 00323 if(MMA6800_READ_X & cu8Axis) 00324 { 00325 if(MMA6800_READ_Y & cu8Axis) 00326 { 00327 u8Counter++; 00328 } 00329 else 00330 { 00331 /* Nothing */ 00332 } 00333 } 00334 else if(MMA6800_READ_Y & cu8Axis) 00335 { 00336 u8Offset++; 00337 } 00338 else 00339 { 00340 /* Nothing */ 00341 } 00342 00343 /* Here, we'll calculate the index for the table based on the above */ 00344 /* operations. */ 00345 u8Index = (uint8_t)((uint8_t)2u * cu8ConfigMemory) + u8Offset; 00346 00347 /* Depending on what type of accelerometer is the type of request */ 00348 /* that we will be performing. */ 00349 if(MESQUITE == cu8Accel) 00350 { 00351 pu16AccelTable = (uint16_t*)&cau16MMA6800PerformAccelReading[u8Index]; 00352 } 00353 else if(SYCAMORE == cu8Accel) 00354 { 00355 pu16AccelTable = (uint16_t*)&cau16MMA6500PerformAccelReading[u8Index]; 00356 00357 } 00358 else 00359 { 00360 /* Accelerometer is not defined */ 00361 u8Status = MMA6800_ERROR_ACCEL; 00362 } 00363 00364 /* Perform the transfer, either automatically or scheduled */ 00365 u8Status 00366 = (*u8pfnMMA6800BatchOp[cu8TransferMode])(cu8DSPIInstance, 00367 cu8ChipSelect, 00368 (const uint16_t*)pu16AccelTable, 00369 pu16AccelResults, u8Counter); 00370 00371 if(MMA6800_TRANSFER_MODE_IS_IMMEDIATE == cu8TransferMode) 00372 { 00373 u8Status |= u8fnMMA6800ExtractAccelResponse(pu16AccelResults, 00374 pu16AccelResults, u8Counter, 00375 cu8Accel); 00376 } 00377 else 00378 { 00379 /* We are done */ 00380 } 00381 } 00382 00383 return (u8Status); 00384 } 00385 /* 00386 ****************************************************************************** 00387 * u8fnMMA6800ExtractRegisterResponse 00388 ****************************************************************************** 00389 */ 00390 uint8_t u8fnMMA6800ExtractRegisterResponse(const uint16_t* pu16RawResponse, 00391 uint8_t* pu8Response, 00392 uint8_t u8Size) 00393 { 00394 /* Declare local variables */ 00395 uint8_t u8Status; 00396 uint8_t u8Counter; 00397 00398 /* Init local variables */ 00399 u8Status = CLEAR; 00400 u8Counter = CLEAR; 00401 00402 for(; u8Counter < u8Size; u8Counter++) 00403 { 00404 /* Check Parity */ 00405 if(CLEAR == u16fnCheckOddParity(*pu16RawResponse, CLEAR)) 00406 { 00407 /* Is this a register operation? */ 00408 u8Status |= u8fnMMA6800ResponseAnalysis(*pu16RawResponse); 00409 if(MMA6800_REGISTER_RESPONSE == u8Status) 00410 { 00411 u8Status = CLEAR; 00412 *pu8Response = (uint8_t)*pu16RawResponse; 00413 } 00414 else 00415 { 00416 *pu8Response = CLEAR; 00417 } 00418 00419 } 00420 else 00421 { 00422 /* If invalid parity is found, clear this particular response, */ 00423 /* and make sure to flag it in the status byte. */ 00424 u8Status |= MMA6800_INVALID_PARITY; 00425 *pu8Response = CLEAR; 00426 } 00427 00428 pu16RawResponse++; 00429 pu8Response++; 00430 } 00431 return (u8Status); 00432 } 00433 /* 00434 ****************************************************************************** 00435 * u8fnMMA6800ExtractAccelResponse 00436 ****************************************************************************** 00437 */ 00438 uint8_t u8fnMMA6800ExtractAccelResponse(const uint16_t* pu16RawResponse, 00439 uint16_t* pu16Response, 00440 uint8_t u8Size, 00441 const uint8_t cu8Accel) 00442 { 00443 /* Declare local variables */ 00444 uint8_t u8Status; 00445 uint8_t u8Counter; 00446 00447 /* Init local variables */ 00448 u8Status = CLEAR; 00449 u8Counter = CLEAR; 00450 00451 for(; u8Counter < u8Size; u8Counter++) 00452 { 00453 /* Check Parity */ 00454 if(CLEAR == u16fnCheckOddParity(*pu16RawResponse, CLEAR)) 00455 { 00456 /* Is this a register operation? */ 00457 u8Status = u8fnMMA6800ResponseAnalysis(*pu16RawResponse); 00458 if(MMA6800_ACCEL_READING == u8Status) 00459 { 00460 u8Status = CLEAR; 00461 if (MESQUITE == cu8Accel) 00462 { 00463 *pu16Response = *pu16RawResponse & MMA6800_RAW_ACCEL_MASK; 00464 } 00465 else if (SYCAMORE == cu8Accel) 00466 { 00467 *pu16Response = *pu16RawResponse & MMA6500_RAW_ACCEL_MASK; 00468 /* Format the 12-bits word with D0 in LSB and D11 in BIT12 location*/ 00469 *pu16Response = (((0xC000u & *pu16Response) >> 14) | (*pu16Response << 2)); 00470 } 00471 else 00472 { 00473 /* Accelerometer is not defined */ 00474 u8Status = MMA6800_ERROR_ACCEL; 00475 } 00476 } 00477 else 00478 { 00479 *pu16Response = 0xFC00; 00480 } 00481 00482 } 00483 else 00484 { 00485 /* If invalid parity is found, clear this particular response, */ 00486 /* and make sure to flag it in the status byte. */ 00487 u8Status |= MMA6800_INVALID_PARITY; 00488 *pu16Response = 0xFC00; 00489 } 00490 00491 pu16RawResponse++; 00492 pu16Response++; 00493 } 00494 return (u8Status); 00495 } 00496 /* 00497 ****************************************************************************** 00498 * u8fnMMA6800ResponseAnalysis 00499 ****************************************************************************** 00500 */ 00501 static uint8_t u8fnMMA6800ResponseAnalysis(uint16_t u16RawResponse) 00502 { 00503 /* Declare local variables */ 00504 uint8_t u8Status; 00505 00506 /* Init local variables */ 00507 u8Status = CLEAR; 00508 00509 if(MMA6800_REGISTER_RESP_SIGNATURE == ((BIT11 | BIT10) & u16RawResponse)) 00510 { 00511 /* This datagram is either a message or an error */ 00512 u8Status = u8fnMMA6800ErrorResponseAnalysis(u16RawResponse); 00513 00514 if(CLEAR == u8Status) 00515 { 00516 u8Status = MMA6800_REGISTER_RESPONSE; 00517 } 00518 else 00519 { 00520 /* Report the status byte provided by the called routine */ 00521 } 00522 } 00523 else 00524 { 00525 /* This message is likely an accel reading */ 00526 u8Status = MMA6800_ACCEL_READING; 00527 } 00528 00529 return (u8Status); 00530 00531 } 00532 /* 00533 ****************************************************************************** 00534 * u8fnMMA6800ErrorResponseAnalysis 00535 ****************************************************************************** 00536 */ 00537 static uint8_t u8fnMMA6800ErrorResponseAnalysis(const uint16_t cu16ReceivedWord) 00538 { 00539 uint8_t u8Status; 00540 00541 u8Status = CLEAR; 00542 00543 /* Once data has been received, check its integrity, starting with */ 00544 /* parity */ 00545 if(CLEAR == u16fnCheckOddParity(cu16ReceivedWord, CLEAR)) 00546 { 00547 /* Identify if error or register operation */ 00548 if((CLEAR == (BIT14 & cu16ReceivedWord)) || (CLEAR == ((BIT13 | BIT9) 00549 & cu16ReceivedWord))) 00550 { 00551 /* Error must be reported */ 00552 u8Status = MMA6800_ERROR_DATAGRAM; 00553 } 00554 else 00555 { 00556 /* We're good! */ 00557 } 00558 } 00559 else 00560 { 00561 u8Status = MMA6800_INVALID_PARITY; 00562 } 00563 00564 return (u8Status); 00565 } 00566 /* 00567 ****************************************************************************** 00568 * u16fnMMA6800AddParityToCommand 00569 ****************************************************************************** 00570 */ 00571 static uint16_t u16fnMMA6800AddParityToCommand(uint16_t u16RawCommand) 00572 { 00573 uint16_t u16Command; 00574 00575 u16Command = CLEAR; 00576 00577 if(u16RawCommand & BIT13) 00578 { 00579 /* This is an acceleration request - parity bit is set at the end of */ 00580 /* datagram. Refer to spec for more info. */ 00581 u16Command = u16fnCheckOddParity(u16RawCommand, BIT0); 00582 } 00583 else 00584 { 00585 /* This is a register operation. Parity bit is set in MSB. Refer to */ 00586 /* spec for more info. */ 00587 u16Command = u16fnCheckOddParity(u16RawCommand, BIT15); 00588 } 00589 00590 return (u16Command); 00591 } 00592 /* 00593 ****************************************************************************** 00594 * u8fnMMA6800ScheduledBatchOp 00595 ****************************************************************************** 00596 */ 00597 uint8_t u8fnMMA6800ScheduledBatchOp(const uint8_t cu8DSPIInstance, 00598 const uint8_t cu8ChipSelect, 00599 const uint16_t* pu16DataToSend, 00600 uint16_t* pu16UnfilteredDataReceived, 00601 uint8_t u8Size) 00602 { 00603 uint8_t u8Status; 00604 uint16_t u16Counter; 00605 uint16_t au16CurrentWordsToSend[MMA6800_MSG_BUFFER_SIZE]; 00606 00607 /* Init locals */ 00608 u8Status = CLEAR; 00609 u16Counter = CLEAR; 00610 00611 /* Next, we shall send the rest of the datagram and store the read-back */ 00612 for(u16Counter = CLEAR; u16Counter < u8Size; u16Counter++) 00613 { 00614 /* Check parity. */ 00615 au16CurrentWordsToSend[u16Counter] = 00616 u16fnMMA6800AddParityToCommand(*(pu16DataToSend++)); 00617 } 00618 /* Write a dummy to recoup the last response */ 00619 au16CurrentWordsToSend[u16Counter] 00620 = u16fnMMA6800AddParityToCommand(MMA6800_SN0); 00621 00622 /* We must wait for the previous transmission to end before launching */ 00623 /* a new one. We must also make sure we don't stay here forever. */ 00624 00625 /* If we came out of the above wait without expiring the timer, we */ 00626 /* should continue. otherwise, flag as an error. */ 00627 u8Status = u8fnSchedDSPIMailTransfer(cu8DSPIInstance, cu8ChipSelect, CLEAR, 00628 CLEAR, 00629 (uint16_t*)au16CurrentWordsToSend, 00630 pu16UnfilteredDataReceived, 00631 (uint16_t)(u8Size + 1u)); 00632 00633 return (u8Status); 00634 } 00635 /* 00636 ****************************************************************************** 00637 * u8fnMMA6800BatchOp 00638 ****************************************************************************** 00639 */ 00640 uint8_t u8fnMMA6800BatchOp(const uint8_t cu8DSPIInstance, 00641 const uint8_t cu8ChipSelect, 00642 const uint16_t* pu16DataToSend, 00643 uint16_t* pu16UnfilteredDataReceived, uint8_t u8Size) 00644 { 00645 uint8_t u8Status; 00646 uint16_t u16Counter; 00647 uint16_t u16TimeOut; 00648 uint16_t u16CurrentWordToSend; 00649 uint16_t u16FirstWordReceived; 00650 00651 /* Init locals */ 00652 u8Status = CLEAR; 00653 u16Counter = CLEAR; 00654 u16TimeOut = CLEAR; 00655 u16CurrentWordToSend = CLEAR; 00656 u16FirstWordReceived = CLEAR; 00657 00658 /* Use DSPI to send config - we need to send one more word since the result*/ 00659 /* will be sent with the second one. The content of the last word is */ 00660 /* irrelevant. */ 00661 00662 /* First, send the first word and simply ignore whatever is received */ 00663 /* Check parity. */ 00664 u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(*(pu16DataToSend++)); 00665 u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect, 00666 (uint16_t*)&u16CurrentWordToSend, 00667 (uint16_t*)&u16FirstWordReceived, 1u); 00668 00669 /* Next, we shall send the rest of the datagram and store the read-back */ 00670 for(u16Counter = 1u; u16Counter < u8Size; u16Counter++) 00671 { 00672 /* Only proceed if we are clear to go */ 00673 if(CLEAR == u8Status) 00674 { 00675 /* Check parity. */ 00676 u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(*(pu16DataToSend++)); 00677 00678 /* We must wait for the previous transmission to end before launching */ 00679 /* a new one. We must also make sure we don't stay here forever. */ 00680 u16TimeOut = CLEAR; 00681 while((u8fnIsDSPIBusy(cu8DSPIInstance >> 4u)) && 00682 (USHRT_MAX > u16TimeOut)) 00683 { 00684 u16TimeOut++; 00685 } 00686 00687 /* If we came out of the above wait without expiring the timer, we */ 00688 /* should continue. otherwise, flag as an error. */ 00689 if((USHRT_MAX) > u16TimeOut) 00690 { 00691 u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect, 00692 (uint16_t*)&u16CurrentWordToSend, 00693 pu16UnfilteredDataReceived++, 1u); 00694 } 00695 else 00696 { 00697 /* There's something wrong */ 00698 u8Status = MMA6800_TIMED_OUT; 00699 } 00700 } 00701 else 00702 { 00703 /* Loop til we exit */ 00704 } 00705 } 00706 00707 /* Only go on if we still can */ 00708 if(CLEAR == u8Status) 00709 { 00710 /* Dummy write just to get the last response */ 00711 /* Check parity. */ 00712 u16CurrentWordToSend = u16fnMMA6800AddParityToCommand(MMA6800_SN0); 00713 00714 /* If we came out of the above wait without expiring the timer, we */ 00715 /* should continue. otherwise, flag as an error. */ 00716 u16TimeOut = CLEAR; 00717 while((u8fnIsDSPIBusy(cu8DSPIInstance >> 4u)) && (USHRT_MAX > u16TimeOut)) 00718 { 00719 u16TimeOut++; 00720 } 00721 /* If we came out of the above wait without expiring the timer, we */ 00722 /* should continue. otherwise, flag as an error. */ 00723 if((USHRT_MAX) > u16TimeOut) 00724 { 00725 u8Status = u8fnDSPITranscieve(cu8DSPIInstance, cu8ChipSelect, 00726 (uint16_t*)&u16CurrentWordToSend, 00727 pu16UnfilteredDataReceived, 1u); 00728 } 00729 else 00730 { 00731 /* There's something wrong */ 00732 u8Status = MMA6800_TIMED_OUT; 00733 } 00734 } 00735 else 00736 { 00737 /* Just get out of here please */ 00738 } 00739 00740 return (u8Status); 00741 } 00742 /* 00743 ****************************************************************************** 00744 * 00745 * End of file. 00746 * 00747 ****************************************************************************** 00748 */